package hr.fer.pus.dll_will.cr.actions;

import java.io.IOException;
import java.net.URLDecoder;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;

import hr.fer.pus.dll_will.cr.IActionHandler;
import hr.fer.pus.dll_will.sherlock.Security;
import hr.fer.pus.dll_will.sp.SPDescriptor;

public class RegisterSP implements IActionHandler {

	private String crPrivateKey;
	private Map<String, KeyPair> spKeys;

	private List<SPDescriptor> sps;

	public RegisterSP(String crPK, Map<String, KeyPair> spkeys,
			List<SPDescriptor> sps) {
		this.crPrivateKey = crPK;
		this.spKeys = spkeys;
		this.sps = sps;
	}

	@Override
	public boolean performAction(ServletOutputStream out,
			HttpServletRequest request) throws IOException {

		String req = request.getParameter("sp");
		req = URLDecoder.decode(req, "UTF-8");
		
		System.out.println("CR registering SP: " + req);
		String[] spl = req.split(" ");

		//String spName = spl[0]; // Not used... but its better than id..
		String spAddress = spl[1];

		KeyPair keyPair = Security.generateKeys();

		// create new sp ID and save key pair
		Integer spID = spKeys.size();
		
		SPDescriptor spd = new SPDescriptor(spID.toString(), spAddress);
		sps.add(spd);
		
		spKeys.put(spID.toString(), keyPair);
		// respond to sp with his new key pair encrypted with CR private key
		// response format: spID modulus privateExponent publicExponent
		String modulus, privateExp, publicExp;
		RSAPrivateKey pk = (RSAPrivateKey) keyPair.getPrivate();
		modulus = pk.getModulus().toString();
		privateExp = pk.getPrivateExponent().toString();
		publicExp = ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()
				.toString();

		StringBuilder sb = new StringBuilder();
		sb.append(spID);
		sb.append(" ");
		sb.append(modulus);
		sb.append(" ");
		sb.append(publicExp);
		
		String coded = Security.encrypt(sb.toString(), crPrivateKey);
		privateExp = Security.encrypt(privateExp, crPrivateKey);
		coded += "#" + privateExp;
		out.write(coded.getBytes());

		return true;
	}

}
